/**
 * 回调函数首先是一个函数
 * 函数作为参数传递给另一个函数（某一时刻，回来调用的函数）
 * 作为参数传递的函数就是回调函数
 */

// 在这个案例中，回调函数就是f()，其实就是m,因为他被以参数的形式传递进了my函数中
function my (f) {
  f()
}

// my(function(){
//   console.log("函数执行")
// })
let m = function () {
  console.log('测试回调函数')
}
// my(m)

// 需求，2秒后产生一个随机数
function getRandWithTime () {
  setTimeout(() => {
    return Math.floor(Math.random() * 10)
  }, 1000)
}
// console.log(getRandWithTime()) //undefined
// 因为setTimeout是一个新函数, 而不是我们的getRandWithTime函数, 所以不能return到getRandWithTime调用处
// setTimeout 是异步的，它不会等待定时器结束就会继续执行后续的代码。因此，getRandWithTime 函数本身没有返回值
// 想要解决这个问题就需要使用Promise或者回调函数

// 使用Promise的方式
// 这个主要是利用了异步的特性，让我们可以拿到异步函数的值
// 其实并没有涉及到在函数的外部使用函数内部变量的情形
function getRandWithTime2 () {
  return new Promise((resolve) => {
    setTimeout(() => {
      const random = Math.floor(Math.random() * 10)
      resolve(random)
    }, 1000)
  })
}

// getRandWithTime2().then(res => {
//   console.log(res);
// })

// 回调函数的作用之一就是从函数的外部获取函数内部的值
// 解决: 使用回调函数接收,这样就可以在这个函数的外部获取到函数内部的私有数据
// 1. 在上面函数 - 声明形参 - fn
function getRandWithTime3 (callback) {
  setTimeout(function () {
    // 3. 因为return不出去, 使用fn()回调外部函数-同时调用传值
    const random = Math.floor(Math.random() * 10)
    callback(random)
  }, 1000) // 2秒后产生随机数 - 比如抽奖啊
}
// 2.声明一个用于处理getRandWithTime3值的工具函数
// 注意，正常情况下，etRandWithTime3内部的值我们是无法获取的，但是通过这个回调函数的形式，我们可以在函数体的外部
// 获取到这个函数内部的变量和数据，最终可以操作函数体的内部，这个就是回调函数的优势
function handleResult (result) {
  console.log(result);
}
// 2. 在调用getRandWithTime3时, 给callback - 传入一个函数体 - 等着接收结果
// getRandWithTime3(handleResult)

// 异步操作使用的也是回调函数，把函数体内部的数据传递出去
// fetch('https://www.sss/foods').then(res => {
//   console.log(res)
// })

const list = [1, 2, 3, 4]

const double = n => {
  return n * 2
}

// 数组的循环方法中有很多使用的就是回调函数的格式
// map后面就是一个回调函数，后面可以看出来every,some和filter都是采用了回调函数的格式
// 这里自定义的 double 和 isMoreThanThree 就是回调函数
// 而是用他们的map every some 和 filter则是高阶函数
const doubleList = list.map(double)

// console.log(doubleList)

const isMoreThanThree = e => {
  return e > 3
}

const isListAllMoreThanThree = list.every(isMoreThanThree)

// console.log(isListAllMoreThanThree);

const isListSomeMoreThanThree = list.some(isMoreThanThree)

// console.log(isListSomeMoreThanThree);

const moreThanThreeInList = list.filter(isMoreThanThree)

// console.log(moreThanThreeInList);
